home *** CD-ROM | disk | FTP | other *** search
- /*
- File: PictMovier.c
-
- Contains: Application to make a movie from PICTs with various processes
-
- Written by: Mark Krueger
- Copyright: © 1990-1991 by Apple Computer, Inc., all rights reserved.
-
- This example shows how you can make movies by doing processing on pictures.
-
- This allows a process that takes a long time to be shown at much faster rates
- as a QuickTime movie. Any type of processing can be done, such as filtering,
- transitions, 3-D transformations. This example shows two trivial examples.
-
- The first simple does a linear cross fade between two images. The second creates
- a random dot stereogram ( an image that if you stare at it long enough you can
- see three dimensional depth in ( without special glasses ). This works from a single
- image and shows how the effect can be varied from frame to frame.
-
- Note that the code is not necessarily well commented, but should prove useful as
- a jumping off point for making your own movie creation applications.
-
- Change History:
- Friday, June 5, 1992 3:27:34 PM MHK New Today
- Nov. 16th, 1993 RMF - Merged into this program ImportExportMovie.c example,
- and added options for selecting effect for PiictMovier.c and show preview
- Jan 17th, 194 RMF - Added option to append movie to existing movie (see DoMovie()).
-
- */
-
- #include "gGlobals.h"
-
- #include <pascal.h>
- #include <Scrap.h>
- #include <Desk.h>
- #include <string.h>
- #include <stdio.h>
- #include <Fonts.h>
- #include <Math.h>
-
-
- void DoRoll(long stageNum,long totalStages, int direction, int rollfill);
- CWindowPtr MakeSWindow(Rect *frame,StringPtr name,GWorldPtr buffer);
-
- /*
- Close a window
-
- */
- DoClose(WindowPtr wind)
- {
- if ( wind == nil) return(0);
- if ( gActiveWindow == wind ) gActiveWindow = nil;
-
- if ( wind == (WindowPtr)gSrcWindow ) {
- DoClear();
- gSrcWindow = nil;
- DisposeGWorld(gWorld);
- gWorld = nil;
- } else
- if ( wind == (WindowPtr)gAltWindow ) {
- DoClear();
- gAltWindow = nil;
- DisposeGWorld(gAltWorld);
- gAltWorld = nil;
- } else
- if ( wind == (WindowPtr)gDstWindow ) {
- gDstWindow = nil;
- }
- CloseWindow(wind);
- return(0);
- }
-
-
-
- void DoStage(long stageNum,long totalStages,Boolean reverse)
- {
-
- switch ( gDoCrossFade ) {
- case EFFECT_CrossFad:
- DoCrossFade(stageNum,totalStages,reverse);
- break;
- case EFFECT_Roll_Left:
- case EFFECT_Roll_Right:
- case EFFECT_Roll_Down:
- case EFFECT_Roll_Up:
- DoRoll(stageNum,totalStages, gDoCrossFade - EFFECT_Roll_Left + 1, gDoRollFill);
- break;
- case EFFECT_StereoGram:
- DoRandomDotStereogram(stageNum,totalStages,reverse);
- break;
- }
- }
-
- /*********************************************
-
- This processing routine creates a random dot stereogram of the input picture.
- The second picture is not used.
-
-
- ********************************************/
-
- void DoRandomDotStereogram(long stageNum,long totalStages,Boolean reverse)
- {
- /* StdFile stuff */
-
- CGrafPtr savePort;
- GDHandle saveGD;
- char *ip,*rp,*pp,*opp,*qp;
- char *sip,*srp,*spp;
- short rowBytes;
- short sRowBytes;
- char mode = 1;
-
- /* for sepecifying compression */
-
- short i,j,x,y,height,width;
- unsigned char pix,spix,ppix,qpix;
-
- char *lineBuf = nil;
- char *newLineBuf = nil;
- char *tLineBuf = nil;
- unsigned long timeseed;
-
-
- #define RDS_DEPTH_FACTOR_VARIES // set this to increase depth as movie progresses
-
- #define RDS_STRIP_WIDTH_VARIES // set this to increase repeat strip as movie progresses
-
- // #define RDS_NEW_SEED_EACH_FRAME // set this to have a new random background for each frame
-
- #ifdef RDS_NEW_SEED_EACH_FRAME
- GetDateTime(×eed);
- rand(time);
- #else
- rand(1);
- #endif
-
- #ifdef RDS_DEPTH_FACTOR_VARIES
- gDepthFactor = 1 + (stageNum * 64) / totalStages;
- gDepthDecodeTabInted = false;
- #else
- gDepthFactor = 16;
- #endif
-
- #ifdef RDS_STRIP_WIDTH_VARIES
- gStripWidth = 32 + (stageNum * 256) / totalStages;
- #else
- gStripWidth = 128;
- #endif
-
- GetGWorld(&savePort,&saveGD);
- SetGWorld(gDstWorld,nil);
- EraseRect(&gDstWorld->portRect);
- width = gWorld->portRect.right - gWorld->portRect.left;
- height = gWorld->portRect.bottom - gWorld->portRect.top;
- LockPixels(gWorld->portPixMap);
- sRowBytes = (*gWorld->portPixMap)->rowBytes & 0x7fff;
- sip = GetPixBaseAddr(gWorld->portPixMap);
- SetGWorld(gDstWorld,nil);
-
- LockPixels(gDstWorld->portPixMap);
- rowBytes = (*gDstWorld->portPixMap)->rowBytes & 0x7fff;
- ip = GetPixBaseAddr(gDstWorld->portPixMap);
-
- lineBuf = NewPtr(sRowBytes);
- if ( lineBuf == nil ) {
- Error("allocating line buffer",0);
- goto done;
- }
- newLineBuf = NewPtr(rowBytes);
- if ( newLineBuf == nil ) {
- Error("allocating nline buffer",0);
- goto done;
- }
- tLineBuf = NewPtr(sRowBytes);
- if ( tLineBuf == nil ) {
- Error("allocating tline buffer",0);
- goto done;
- }
- SwapMMUMode(&mode);
- if ( gDepth == 1 ) {
-
- rp = ip;
- for(y=0; y<height; y++) {
- pp = rp;
- for(x=0;x<gStripWidth/8;x++,pp++) {
- pix = 0;
- for ( i=0; i < 8; i++ ) {
- pix <<= 1;
- if ( rand(0) % 5 == 0 )
- pix |= 1;
- }
- qp = pp;
- for ( j=0; j < width/gStripWidth; j++ ) {
- *qp = pix;
- qp += gStripWidth /8;
- }
- }
- rp += rowBytes;
- }
- rp = ip;
- srp = sip;
-
-
- for(y=0;y<height;y++) {
- pp = rp;
- spp = srp;
- spp += gDepthFactor/8;
- qp = pp;
- BlockMove(pp,tLineBuf,sRowBytes);
- qp = tLineBuf;
- pp = qp;
- qp += gDepthFactor/8;
-
- opp = newLineBuf;
- for(x=0;x < width/8-gStripWidth/8;x++ ,pp++,qp++,opp++) {
- spix = *spp++;
- qpix = *qp;
- ppix = *pp;
- pix = 0;
- for ( i=0; i < 8; i++ ) {
- pix <<= 1;
- if ( (spix & 0x80 ) )
- pix |= (qpix & 0x80) != 0 ? 1 : 0;
- else
- pix |= (ppix & 0x80) != 0 ? 1 : 0;
- spix <<= 1;
- ppix <<= 1;
- qpix <<= 1;
- }
- *opp = pix;
- *(pp+gStripWidth/8) = pix;
- }
- BlockMove(newLineBuf,rp+gStripWidth/8,rowBytes-gStripWidth/8);
- rp += rowBytes;
- srp += sRowBytes;
- }
- } else
-
- if ( gDepth == 8 || gDepth == 40 ) {
-
- rp = ip;
-
- for(y=0; y<height; y++) {
- pp = rp;
- for(x=0;x<gStripWidth;x++) {
- *pp++ = rand(0);
- }
- rp += rowBytes;
- }
-
- rp = ip;
- srp = sip;
-
- for(y=0;y<height;y++) {
- pp = rp;
- spp = srp;
- spp += gStripWidth;
-
- qp = pp;
- BlockMove(pp,tLineBuf,sRowBytes);
- qp = tLineBuf;
- pp = qp;
-
- opp = newLineBuf;
- for(x=0;x < width-gStripWidth;x++ ,pp++,qp++,opp++) {
- spix = *spp++;
- ppix = *pp;
-
- pix = *(qp + DecodeDepth(spix));
- *opp = pix;
- *(pp+gStripWidth) = pix;
- }
- BlockMove(newLineBuf,rp+gStripWidth,rowBytes-gStripWidth);
- rp += rowBytes;
- srp += sRowBytes;
- }
- }
- SwapMMUMode(&mode);
- UnlockPixels(gDstWorld->portPixMap);
-
- SetGWorld(savePort,saveGD);
- done:
- if ( newLineBuf )
- DisposPtr(newLineBuf);
- if ( lineBuf )
- DisposPtr(lineBuf);
- if ( tLineBuf )
- DisposPtr(tLineBuf);
-
-
- }
-
- /*********************************************
-
- a better random function than the one in the ROM
-
- *********************************************/
-
- long rand(long reseed)
- {
- #define A 16807
- #define M 2147483647
- #define Q 127773
- #define R 2836
-
- static long seed = 1;
-
- long lo,hi,test;
-
- if ( reseed != 0 )
- seed = reseed;
- hi = seed / Q;
- lo = seed % Q;
- test = A*lo - R*hi;
- if ( test > 0 )
- seed = test;
- else
- seed = test + M;
- return ( seed/(M>>16));
- }
-
- unsigned char DecodeDepth(unsigned char pix)
- {
- static unsigned char table[256];
- short i;
-
- if ( !gDepthDecodeTabInted ) {
- gDepthDecodeTabInted = 1;
- for ( i=0; i < 255; i++ ) {
- table[i] = (i * gDepthFactor)/255;
- }
- }
- return(table[pix]);
- }
-
- /*********************************************
-
- This processing routine does a linear cross dissolve between the two images,
- using CopyBits with blend mode. It shows how to do a process which involves
- both images. Any type of process could be done here, using the three parameters
- to determine how much of the processing has progressed.
-
- Note: See the Develop article by Konstantin Othmar ( sorry I forget the issue number )
- about CopyBits to learn how to do other cool effects just using CopyBits.
-
- *********************************************/
-
- void DoCrossFade(long stageNum,long totalStages,Boolean reverse)
- {
- GWorldPtr saveWorld;
- GDHandle saveGD;
- RGBColor opColor;
-
-
- if ( reverse )
- opColor.red = opColor.green = opColor.blue = (stageNum*0xffff)/totalStages;
- else
- opColor.red = opColor.green = opColor.blue = ((totalStages-stageNum)*0xffff)/totalStages;
-
- GetGWorld(&saveWorld,&saveGD);
-
- SetGWorld(gDstWorld,nil);
- CopyBits((BitMap *)*gAltWorld->portPixMap,(BitMap *)*gDstWorld->portPixMap,
- &gAltWorld->portRect,&gDstWorld->portRect,ditherCopy,nil);
- OpColor(&opColor);
- CopyBits((BitMap *)*gWorld->portPixMap,(BitMap *)*gDstWorld->portPixMap,
- &gWorld->portRect,&gDstWorld->portRect,blend,nil);
- SetGWorld(saveWorld,saveGD);
-
- } /* End of () */
-
- /*********************************************
-
- Create the movie by processing all the frames.
-
- ********************************************/
- OSErr OpenCreateMovie(Boolean Append, Movie *gMovie, short *resRefNum, short *resID, SFReply *sfr)
- { OSErr result;
- FSSpec mySpec; /* Data structure with filename, etc. */
-
- ClearMoviesStickyError(); /* Clear any old errors */
- result = FSMakeFSSpec(sfr->vRefNum, 0, (unsigned char *) sfr->fName, &mySpec);
- if (result == fnfErr) result = 0;
-
- if (Append) { /* RMF */
- // Open a movie file using the FSSpec and create a movie from that file.
-
- result = OpenMovieFile(&mySpec, resRefNum, fsRdWrPerm);
- if (result == noErr) {
- result = NewMovieFromFile(gMovie,*resRefNum, resID, nil,newMovieActive, nil);
- }
- } else
- result = CreateMovieFile( &mySpec, 'TVOD',0,createMovieFileDeleteCurFile, resRefNum, gMovie);
- return result;
- } /* End of () */
-
- CWindowPtr OpenReplaceMovieWindow(StringPtr name, short width, short height)
- { Rect rect;
- if ( gDstWindow ) {
- CloseWindow((WindowPtr)gDstWindow);
- gDstWindow = nil;
- }
- SetRect(&rect,80,80, width+80, height+80);
- gDstWindow = MakeSWindow(&rect, name, nil);
-
- return gDstWindow;
- } /* End of () */
-
- OSErr DoMovie(Boolean Append)
- { GWorldPtr saveWorld;
- GDHandle saveGD;
- short resRefNum, resID = 0;
- OSErr result;
-
- /* Stuff for creating the file */
-
- SFReply sfr; /* StdFile reply */
- Movie gMovie = 0; /* Our movie, track and media */
- Track gTrack, gTackOld;
- Media gMedia;
- long maxCompressedFrameSize; /* Max size of compressed frame */
- long compressedFrameSize; /* Size of current compressed frame */
- Handle compressedFrameBitsH = nil; /* Buffer for the compressed data */
- ImageDescription **imageDescriptionH = nil; /* Contains info about the sample */
- Ptr data;
- EventRecord myEvent;
- ImageSequence seq;
- Rect dstRect;
- short i, width,height;
-
- TimeValue MyMediaDuration, timeLength, sampleDuration;
- Boolean foundVideo;
-
- GetGWorld(&saveWorld,&saveGD);
-
- /* Prompt the user for a file name and create it */
- if (Append) { /* RMF */
- Point where;
- SFTypeList typeList;
- //---------------------------------------------------------------------------------------------
- // Ask for a source movie file using Standard Preview.
- // Use (-2,-2) to center on the best device.
- //---------------------------------------------------------------------------------------------
-
- where.h = where.v = -2;
- typeList[0] = 'MooV';
- SFGetFilePreview(where,"\p", nil,1,typeList,nil, &sfr);
-
- } else {
- static Str255 name = "\pMovieToolBox Movie";
- Point where;
- where.h = where.v = -2;
- SFPutFile(where, (StringPtr) "\pMovie file to create:",(StringPtr)name,nil,&sfr);
- if (sfr.good)
- BlockMove(sfr.fName,name,sfr.fName[0]+1);
- }
- if (!sfr.good) return;
-
-
- width = gRect.right - gRect.left;
- height = gRect.bottom - gRect.top;
- if ( gOversample ) {
- width /= 2;
- height /= 2;
- }
-
- if (OpenReplaceMovieWindow(sfr.fName, width, height) == nil) goto done; /* Error opening window */
-
- imageDescriptionH = (ImageDescription **)NewHandle( sizeof( ImageDescription)); /* handle for image descriptor */
- if ( imageDescriptionH == nil ) {
- Error("Out of Memory",MemError());
- goto done;
- }
-
- result = OpenCreateMovie(Append, &gMovie, &resRefNum, &resID, &sfr);
-
- if (result == noErr) result = GetMoviesError();
- if (result != noErr) {
- Error("Opening Movie file", result); goto done;
- }
-
-
- /* Find a movie's video track. */
- // RMF
- foundVideo = false;
- for (i=1; ((i<=GetMovieTrackCount(gMovie)) && (!foundVideo)); i++) {
- OSType myMediaType;
-
- gTrack = GetMovieIndTrack(gMovie, i);
- gMedia = GetTrackMedia(gTrack);
- GetMediaHandlerDescription(gMedia, &myMediaType, nil, nil);
- if (myMediaType == VideoMediaType)
- foundVideo = true;
- } /* End for() */
- // RMF
- if (foundVideo == true) {
- timeLength = GetMediaDuration(gMedia);
- } else {
- timeLength = 0L;
-
- gTrack = NewMovieTrack(gMovie,(long)width<<16, (long)height<<16, 0 /* volume */);
- gMedia = NewTrackMedia(gTrack, VideoMediaType, gStandardP.frameRate>>16L, nil,(OSType) nil);
- // SetMediaTimeScale(gMedia, 1);
- }
- BeginMediaEdits( gMedia ); /* adding samples to the media */
- GetMaxCompressionSize(gAltWorld->portPixMap,&gAltWorld->portRect,
- gStandardP.depth,gStandardP.spatialQuality,
- gStandardP.theCodecType,gStandardP.theCodec,&maxCompressedFrameSize);
-
- compressedFrameBitsH = NewHandle(maxCompressedFrameSize);
- if ( compressedFrameBitsH == nil ) {
- Error("Out of Memory",MemError()); goto bail;
- }
-
- GetGWorld(&saveWorld,&saveGD);
- SetGWorld((CGrafPtr)gDstWorld,nil); PaintRect(&gDstWorld->portRect);
-
- if ( (result=CompressSequenceBegin(&seq,gDstWorld->portPixMap,nil,
- &gDstWorld->portRect,nil,gStandardP.depth,gStandardP.theCodecType,
- gStandardP.theCodec,
- gStandardP.spatialQuality,gStandardP.temporalQuality,gStandardP.keyFrameRate,
- nil,codecFlagUpdatePreviousComp,imageDescriptionH)) != 0 ) {
- Error("CompressSequenceBegin Failed. #",result);
- goto bail2;
- }
-
- SetGWorld(saveWorld,saveGD);
- while ( WaitNextEvent( everyEvent, &myEvent, 0, nil) != 0 ) {
- if ( HandleEvents(&myEvent) ) goto bail2; /* RMF - was return; */
- }
-
-
- SetRect(&dstRect, 0,0, gRect.right/2, gRect.bottom/2);
- i = GetMediaTimeScale(gMedia); /* durationPerSample */
- i = 1;
- for ( gFrameNumber=0; gFrameNumber < gNumberSteps; gFrameNumber++ ) {
- SetGWorld(saveWorld,saveGD);
- if ( WaitNextEvent( everyEvent, &myEvent, 0, nil) != 0 ) { /* Do background events... */
- if ( HandleEvents(&myEvent) ) break;
- }
-
- SetGWorld((CGrafPtr)gDstWorld,nil);
- PaintRect(&gDstWorld->portRect);
-
- if ( gDstWorld && gWorld && gAltWorld ) /* Draw the current stage in the buffer */
- DoStage(gFrameNumber, gNumberSteps, gBackwards);
-
- SetGWorld((CGrafPtr)gDstWindow,nil);
- InvalRect(&gDstWindow->portRect);
- DoHLock(compressedFrameBitsH);
- data = StripAddress(*compressedFrameBitsH);
-
- if ( gOversample ) { /* use: gBufferWorld to create oversame image */
- SetGWorld(gBufferWorld,nil);
- CopyBits((BitMap *)*gDstWorld->portPixMap,(BitMap *)*gBufferWorld->portPixMap,
- &gDstWorld->portRect,&dstRect,ditherCopy,nil);
-
- result = CompressSequenceFrame(seq,gBufferWorld->portPixMap,&dstRect,
- codecFlagUpdatePreviousComp,data,&compressedFrameSize,nil,nil);
- } else {
- SetGWorld((CGrafPtr)gDstWorld,nil);
- result = CompressSequenceFrame(seq,gDstWorld->portPixMap,&gDstWorld->portRect,
- codecFlagUpdatePreviousComp,data,&compressedFrameSize,nil,nil);
- }
-
- if ( result ) {
- Error("Compress Sequence Frame Failed. #",result);
- break;
- }
-
- DoHUnlock(compressedFrameBitsH);
-
- result = AddMediaSample(gMedia,
- compressedFrameBitsH, 0L,compressedFrameSize,
- (TimeValue) i, /* durationPerSample */
- (SampleDescriptionHandle) imageDescriptionH,
- 1L, /* numberOfSamples */
- 0, /* sampleFlags */
- &sampleDuration);
- if ( result ) {
- Error("AddMediaSample Failed. #",result); break;
- }
-
- } /* End for() */
- bail2:
- CDSequenceEnd(seq);
-
- bail:
- { TimeValue test;
-
- MyMediaDuration = GetMediaDuration(gMedia);
- test = -1;
- result = InsertMediaIntoTrack(gTrack,
- test, /* -1 = at end, 0L = at start of Track */
- timeLength, /* Media time */
- MyMediaDuration - timeLength, /* amount of data to insert */
- 1<<16); /* Media Rate */
- if ( result ) {
- Error("InsertMediaIntoTrack Failed. #",result);
- }
-
- if (Append) {
- result = UpdateMovieResource(gMovie, resRefNum, resID, nil);
- } else
- result = AddMovieResource(gMovie, resRefNum, &resID, nil);
- if ( result ) {
- Error("AddMovieResource Failed. #",result);
- }
- EndMediaEdits( gMedia ); /* We're done adding samples */
- }
- // MakeFilePreview(resRefNum, (ProgressProcRecordPtr)-1L); /* RMF */
-
- CloseMovieFile( resRefNum );
-
- done:
- SetGWorld(saveWorld,saveGD);
- if ( imageDescriptionH ) DoDisposHandle((Handle)imageDescriptionH);
- if ( compressedFrameBitsH ) DoDisposHandle((Handle)compressedFrameBitsH);
- if ( gMovie ) DisposeMovie(gMovie);
- if ( gDstWindow ) {
- CloseWindow((WindowPtr)gDstWindow);
- gDstWindow = nil;
- }
- SetGWorld(saveWorld,saveGD);
- } /* End of DoMovie() */
-
-
-
-
-
- /********************************************
-
- Update a window
-
- ********************************************/
-
- void DoUpdate(CWindowPtr wind)
- { GWorldPtr saveWorld,gw;
- GDHandle saveGD;
- char c[32];
-
- GetGWorld(&saveWorld,&saveGD);
- if ( wind == gDstWindow ) {
- BeginUpdate((WindowPtr)wind);
- SetGWorld((CGrafPtr)wind,nil);
- CopyBits((BitMap *)*gDstWorld->portPixMap,(BitMap *)*wind->portPixMap,
- &gDstWorld->portRect,&wind->portRect,ditherCopy,nil);
- if ( gFrameNumber >= 0 ) {
- MoveTo(20,20);
- TextSize(12);
- TextFace(bold);
- TextMode(patBic);
- NumToString(gFrameNumber+1,(StringPtr)&c);
- DrawString((StringPtr)&c);
- DrawString((StringPtr)"\p/");
- NumToString(gNumberSteps+1,(StringPtr)&c);
- DrawString((StringPtr)&c);
- MoveTo(21,21);
- TextMode(srcOr);
- NumToString(gFrameNumber+1,(StringPtr)&c);
- DrawString((StringPtr)&c);
- DrawString((StringPtr)"\p/");
- NumToString(gNumberSteps+1,(StringPtr)&c);
- DrawString((StringPtr)&c);
- }
- EndUpdate((WindowPtr)wind);
- SetGWorld(saveWorld,saveGD);
- return;
- }
- SetGWorld(wind,nil);
- gw = (GWorldPtr)GetWRefCon((WindowPtr)wind);
- BeginUpdate((WindowPtr)wind);
- CopyBits((BitMap *)*gw->portPixMap,(BitMap *)*wind->portPixMap,
- &gw->portRect,&wind->portRect,ditherCopy,nil);
- EndUpdate((WindowPtr)wind);
- SetGWorld(saveWorld,saveGD);
- } /* End of () */
-
-
-